<html>
<head><meta charset="utf-8"><title>RefMut lifetime propagation · t-libs · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/index.html">t-libs</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html">RefMut lifetime propagation</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="198523345"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198523345" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198523345">(May 23 2020 at 07:34)</a>:</h4>
<p>I’m having trouble mapping a RefMut containing a DB connection to a corresponding transaction (which contains a lifetime):</p>
<div class="codehilite"><pre><span></span><code><span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">borrow</span>: <span class="nc">RefMut</span><span class="o">&lt;</span><span class="na">&#39;a</span><span class="p">,</span><span class="w"> </span><span class="n">Client</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">conn</span><span class="p">.</span><span class="n">borrow_mut</span><span class="p">();</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">tx</span>: <span class="nc">RefMut</span><span class="o">&lt;</span><span class="na">&#39;a</span><span class="p">,</span><span class="w"> </span><span class="nb">Result</span><span class="o">&lt;</span><span class="n">Transaction</span><span class="p">,</span><span class="w"> </span><span class="n">postgres</span>::<span class="n">Error</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"></span>
<span class="w">            </span><span class="n">RefMut</span>::<span class="n">map</span><span class="p">(</span><span class="n">borrow</span><span class="p">,</span><span class="w"> </span><span class="o">|</span><span class="n">c</span>: <span class="kp">&amp;</span><span class="na">&#39;a</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">Client</span><span class="o">|</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">c</span><span class="p">.</span><span class="n">transaction</span><span class="p">());</span><span class="w"></span>
</code></pre></div>


<p>This gives an error like the following:</p>
<div class="codehilite"><pre><span></span><code>error[E0308]: mismatched types
  --&gt; src/db/postgre.rs:78:37
   |
78 |             RefMut::map(borrow, |c: &amp;&#39;a mut Client| &amp;mut c.transaction());
   |                                     ^^^^^^^^^^^^^^ lifetime mismatch
   |
   = note: expected mutable reference `&amp;mut postgres::client::Client`
              found mutable reference `&amp;&#39;a mut postgres::client::Client`
note: the anonymous lifetime #2 defined on the body at 78:33...
  --&gt; src/db/postgre.rs:78:33
   |
78 |             RefMut::map(borrow, |c: &amp;&#39;a mut Client| &amp;mut c.transaction());
   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime `&#39;a` as defined on the method body at 75:20
  --&gt; src/db/postgre.rs:75:20
   |
75 |     fn transaction&lt;&#39;a&gt;(&amp;&#39;a self) -&gt; RefMut&lt;&#39;a, Result&lt;Transaction&lt;&#39;a&gt;, postgres::Error&gt;&gt; {
   |                    ^^
</code></pre></div>


<p>Am I correct in assuming that this is due to <code>RefMut::map</code> not propagating its <code>'b</code> lifetime to the references in the function signature it takes?</p>



<a name="198524419"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198524419" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198524419">(May 23 2020 at 08:06)</a>:</h4>
<p>In any case, even if this did work, it wouldn’t solve my larger problem (because <code>Transaction::commit</code> consumes <code>self</code>, so a reference won’t do). But I’d still be interested in whether my assumption is correct.</p>



<a name="198527354"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198527354" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198527354">(May 23 2020 at 09:36)</a>:</h4>
<p>try removing the <code>'a</code> in <code>|c: &amp;'a mut Client|</code></p>



<a name="198527364"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198527364" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198527364">(May 23 2020 at 09:37)</a>:</h4>
<p>so yes this is likely related to <code>map</code> taking a generic closure as an argument. and that in turn is crucial for soundness, if it propagated the outer <code>'b</code> that would be unsound.</p>



<a name="198529660"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198529660" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Yato <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198529660">(May 23 2020 at 10:44)</a>:</h4>
<p>You are returning a reference to a temporary in the closure, which would create a dangling reference if this compiled.</p>



<a name="198569587"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198569587" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198569587">(May 24 2020 at 06:41)</a>:</h4>
<p><span class="user-mention" data-user-id="202379">@Yato</span> Yes, indeed, this is another problem hindering abstraction over transaction creation.</p>
<p><span class="user-mention" data-user-id="120791">@RalfJ</span> Why would it be unsound? The reference presented to the closure has lifetime <code>'b</code>, has it not? I’ve seen this pattern of keeping lifetimes generic to make it impossible to return references from a closure (e.g. in the dataflow constructor in differential-dataflow), where I made sense of it by assuming that the framework may kill the underlying resource after the closure but before returning control to my code. For <code>RefMut::map</code> I wouldn’t see why that should be needed, because the purpose of that method is to expose a reference to me, is it not?</p>



<a name="198570415"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570415" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570415">(May 24 2020 at 07:08)</a>:</h4>
<p><span class="user-mention" data-user-id="302838">@Roland Kuhn</span> it's unsound because you could leak the reference, drop the <code>RefMut</code>, and then still use the reference.</p>



<a name="198570416"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570416" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570416">(May 24 2020 at 07:08)</a>:</h4>
<p>basically, the lifetime in <code>RefMut</code> is an <em>upper bound</em> to the lifetime of the reference it contains, but the actual lifetime could be shorter because you can drop the <code>RefMut</code> at any time.</p>



<a name="198570441"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570441" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570441">(May 24 2020 at 07:09)</a>:</h4>
<p>but this is subtle, in fact the first version of this API <em>did</em> propagate the lifetime and it took a bit for people to realize that that is unsound</p>



<a name="198570484"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570484" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570484">(May 24 2020 at 07:10)</a>:</h4>
<p>Hmm, this is something I have not yet fully grasped: I thought that in my snipped <code>'a</code> would describe exactly how long the RefMut exists, so if I drop it then there is a “region of code” described by <code>'a</code> that ends with the drop.</p>



<a name="198570495"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570495" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570495">(May 24 2020 at 07:11)</a>:</h4>
<p>could you point me to the discussions on where this unsoundness was uncovered?</p>



<a name="198570547"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570547" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570547">(May 24 2020 at 07:13)</a>:</h4>
<p>Or to put it differently: how does <code>rustc</code> assign the actual lifetime of the reference passed into the closure?</p>



<a name="198570654"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570654" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570654">(May 24 2020 at 07:16)</a>:</h4>
<p>there is a more detailed description about this <em>somewhere</em> but I cannot find it right now...</p>



<a name="198570655"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570655" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570655">(May 24 2020 at 07:16)</a>:</h4>
<p><span class="user-mention silent" data-user-id="302838">Roland Kuhn</span> <a href="#narrow/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation/near/198570547">said</a>:</p>
<blockquote>
<p>Or to put it differently: how does <code>rustc</code> assign the actual lifetime of the reference passed into the closure?</p>
</blockquote>
<p>hehe, great question! the answer is, it doesnt matter.</p>



<a name="198570660"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570660" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570660">(May 24 2020 at 07:17)</a>:</h4>
<p>this is an unsafe library. the "actual" lifetime used in the closure is one <em>rustc doesnt even know exists</em></p>



<a name="198570662"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570662" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570662">(May 24 2020 at 07:17)</a>:</h4>
<p>but that's okay because in the proof we can construct it, and because of lifetime parametricity we know the code has to work even for lifetimes that it "doesnt know exist"</p>



<a name="198570710"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570710" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570710">(May 24 2020 at 07:19)</a>:</h4>
<p>(for more than a year now I wanted to write a blog post on this but didnt get around to it yet)</p>



<a name="198570733"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570733" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570733">(May 24 2020 at 07:19)</a>:</h4>
<p><span class="user-mention silent" data-user-id="302838">Roland Kuhn</span> <a href="#narrow/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation/near/198570484">said</a>:</p>
<blockquote>
<p>Hmm, this is something I have not yet fully grasped: I thought that in my snipped <code>'a</code> would describe exactly how long the RefMut exists, so if I drop it then there is a “region of code” described by <code>'a</code> that ends with the drop.</p>
</blockquote>
<p>no, <code>'a</code> is just the lifetime of the <code>RefCell</code> reference you passed in</p>



<a name="198570734"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570734" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570734">(May 24 2020 at 07:19)</a>:</h4>
<p>Okay, I get that approach, but still: how does rustc derive the bounds on the lifetimes so that it can check whether a proof exists?</p>



<a name="198570771"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570771" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570771">(May 24 2020 at 07:20)</a>:</h4>
<p><span class="user-mention silent" data-user-id="302838">Roland Kuhn</span> <a href="#narrow/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation/near/198570734">said</a>:</p>
<blockquote>
<p>Okay, I get that approach, but still: how does rustc derive the bounds on the lifetimes so that it can check whether a proof exists?</p>
</blockquote>
<p>it doesnt</p>



<a name="198570778"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570778" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570778">(May 24 2020 at 07:20)</a>:</h4>
<p>when the define <code>map</code> we have to tell it to make the closure generic</p>



<a name="198570779"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570779" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570779">(May 24 2020 at 07:20)</a>:</h4>
<p>take a look at that code</p>



<a name="198570780"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570780" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570780">(May 24 2020 at 07:20)</a>:</h4>
<p>or rather, the type</p>



<a name="198570781"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570781" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570781">(May 24 2020 at 07:20)</a>:</h4>
<p>:-) but it must do something, because I get these nice and fancy ASCII art representations in my errors :D</p>



<a name="198570791"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570791" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570791">(May 24 2020 at 07:21)</a>:</h4>
<p>sure, the signature says: whatever I give you, the result has the same lifetime, deal with it</p>



<a name="198570792"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570792" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570792">(May 24 2020 at 07:21)</a>:</h4>
<p>(man it would be really useful if even for stabilized features we tracked the tracking issue in the source)</p>



<a name="198570794"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570794" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570794">(May 24 2020 at 07:21)</a>:</h4>
<p>found the soundness counterexample: <a href="https://github.com/rust-lang/rust/pull/25747#issuecomment-105175235">https://github.com/rust-lang/rust/pull/25747#issuecomment-105175235</a></p>



<a name="198570833"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570833" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570833">(May 24 2020 at 07:22)</a>:</h4>
<p>cool, thanks; looking</p>



<a name="198570835"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570835" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570835">(May 24 2020 at 07:22)</a>:</h4>
<p>so here's the type:</p>
<div class="codehilite"><pre><span></span><code>    pub fn map&lt;U: ?Sized, F&gt;(orig: RefMut&lt;&#39;b, T&gt;, f: F) -&gt; RefMut&lt;&#39;b, U&gt;
    where
        F: FnOnce(&amp;mut T) -&gt; &amp;mut U,
</code></pre></div>



<a name="198570837"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570837" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570837">(May 24 2020 at 07:22)</a>:</h4>
<p>let's desugar this a bit:</p>
<div class="codehilite"><pre><span></span><code><span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">map</span><span class="o">&lt;</span><span class="n">U</span>: <span class="o">?</span><span class="nb">Sized</span><span class="p">,</span><span class="w"> </span><span class="n">F</span><span class="o">&gt;</span><span class="p">(</span><span class="n">orig</span>: <span class="nc">RefMut</span><span class="o">&lt;</span><span class="na">&#39;b</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="n">f</span>: <span class="nc">F</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">RefMut</span><span class="o">&lt;</span><span class="na">&#39;b</span><span class="p">,</span><span class="w"> </span><span class="n">U</span><span class="o">&gt;</span><span class="w"></span>
<span class="w">    </span><span class="k">where</span><span class="w"></span>
<span class="w">        </span><span class="n">F</span>: <span class="nc">for</span><span class="o">&lt;</span><span class="na">&#39;a</span><span class="o">&gt;</span><span class="w"> </span><span class="nb">FnOnce</span><span class="p">(</span><span class="o">&amp;</span><span class="na">&#39;a</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">T</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kp">&amp;</span><span class="na">&#39;a</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">U</span><span class="p">,</span><span class="w"></span>
</code></pre></div>



<a name="198570842"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570842" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570842">(May 24 2020 at 07:23)</a>:</h4>
<p>notice the <code>for</code>! there's a "nested quantifier" here. that is crucial.</p>



<a name="198570846"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570846" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570846">(May 24 2020 at 07:23)</a>:</h4>
<p>Yes, making the lifetime existential, right?</p>



<a name="198570847"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570847" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570847">(May 24 2020 at 07:23)</a>:</h4>
<p>the unsound version -- the version that would make your code compile -- has a slightly different type:</p>
<div class="codehilite"><pre><span></span><code><span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">map</span><span class="o">&lt;</span><span class="n">U</span>: <span class="o">?</span><span class="nb">Sized</span><span class="p">,</span><span class="w"> </span><span class="n">F</span><span class="o">&gt;</span><span class="p">(</span><span class="n">orig</span>: <span class="nc">RefMut</span><span class="o">&lt;</span><span class="na">&#39;b</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="n">f</span>: <span class="nc">F</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">RefMut</span><span class="o">&lt;</span><span class="na">&#39;b</span><span class="p">,</span><span class="w"> </span><span class="n">U</span><span class="o">&gt;</span><span class="w"></span>
<span class="w">    </span><span class="k">where</span><span class="w"></span>
<span class="w">        </span><span class="n">F</span>: <span class="nb">FnOnce</span><span class="p">(</span><span class="o">&amp;</span><span class="na">&#39;b</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">T</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kp">&amp;</span><span class="na">&#39;b</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">U</span><span class="p">,</span><span class="w"></span>
</code></pre></div>



<a name="198570885"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570885" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570885">(May 24 2020 at 07:24)</a>:</h4>
<p><span class="user-mention silent" data-user-id="302838">Roland Kuhn</span> <a href="#narrow/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation/near/198570846">said</a>:</p>
<blockquote>
<p>Yes, making the lifetime existential, right?</p>
</blockquote>
<p>it's a <em>universal</em> quantification, so... not really if you want to use precise terms</p>



<a name="198570886"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570886" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570886">(May 24 2020 at 07:24)</a>:</h4>
<p>aargh, yes, just realized</p>



<a name="198570888"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570888" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570888">(May 24 2020 at 07:24)</a>:</h4>
<p>different languages use the same keywords for opposite purposes</p>



<a name="198570889"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570889" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570889">(May 24 2020 at 07:24)</a>:</h4>
<p>think of "for" as short for "forall"</p>



<a name="198570890"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570890" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570890">(May 24 2020 at 07:24)</a>:</h4>
<p>(IMO they should have used <code>all</code> or <code>forall</code>, but, well)</p>



<a name="198570894"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570894" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570894">(May 24 2020 at 07:24)</a>:</h4>
<p>and yes, I’m very interested in precise terms! :-)</p>



<a name="198570897"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570897" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570897">(May 24 2020 at 07:25)</a>:</h4>
<p>:D</p>



<a name="198570901"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570901" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570901">(May 24 2020 at 07:25)</a>:</h4>
<p>I think I’ll have to spend some deep thinking minutes on the example to get it — thanks for your help!</p>



<a name="198570952"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570952" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570952">(May 24 2020 at 07:26)</a>:</h4>
<p>yes this is definitely worth pondering, but if you get to the bottom of it you gained a level-up in Rust type system comprehension. ;)</p>



<a name="198570959"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570959" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570959">(May 24 2020 at 07:26)</a>:</h4>
<p>a worthy goal for a Sunday :-)</p>



<a name="198570961"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570961" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570961">(May 24 2020 at 07:26)</a>:</h4>
<p>:) have fun!</p>



<a name="198570969"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198570969" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198570969">(May 24 2020 at 07:27)</a>:</h4>
<p>(I have this stream muted so please @mention me if there's something youd like me to look at, as you did last time)</p>



<a name="198571221"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198571221" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198571221">(May 24 2020 at 07:35)</a>:</h4>
<p><span class="user-mention" data-user-id="120791">@RalfJ</span> That went quicker than I thought, and thanks again: universal quantification is used as a _leak stopper_ (a.k.a. reference containment) because universality includes cases that don’t permit storing references elsewhere, and the problem was that the lifetime of the actual object may be shorter than that of the RefCell (I hadn’t fully absorbed what you said above, but the example makes it clear). Neat trick!</p>



<a name="198571262"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198571262" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198571262">(May 24 2020 at 07:36)</a>:</h4>
<p>Yes that sums it up well :)</p>



<a name="198571269"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198571269" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198571269">(May 24 2020 at 07:36)</a>:</h4>
<p>Now you probably can understand how supremely happy I was when we were actually able to formally prove this trick correct :D</p>



<a name="198571282"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198571282" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Roland Kuhn <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198571282">(May 24 2020 at 07:36)</a>:</h4>
<p>indeed!</p>



<a name="198571294"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/RefMut%20lifetime%20propagation/near/198571294" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/RefMut.20lifetime.20propagation.html#198571294">(May 24 2020 at 07:37)</a>:</h4>
<p>if my PhD thesis wasnt already almost 300 pages I'd be tempted to include a proper description of the <code>RefCell</code> proof in there... but that would be a lot of effort and I am supposed to submit soon so probably not. :/ but a blog post will happen, eventually.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>